﻿namespace GitUI.CommandsDialogs.BrowseDialog;

/// <summary>
/// Represents a menu command with Text, ShortcutKey or ShortcutDisplayString, Action,
/// Icon and optionally CheckBoxes.
/// From a MenuCommand a (theoretically) unlimited number of actual ToolStripItems can
/// be created that all behave the same.
/// A MenuCommand can also be a separator
///
/// Purpose: have methods from specific context menus also available in main menu.
/// </summary>
internal class MenuCommand
{
    public static MenuCommand CreateSeparator()
    {
        return new MenuCommand { IsSeparator = true };
    }

    public static MenuCommand CreateGroupHeader(string text)
    {
        return new MenuCommand
        {
            IsGroupHeader = true,
            Name = text.Replace(' ', '_') + "ToolStripMenuItem",
            Text = text,
        };
    }

    public static ToolStripItem CreateToolStripItem(MenuCommand menuCommand)
    {
        if (menuCommand.IsSeparator)
        {
            return new ToolStripSeparator();
        }

        if (menuCommand.IsGroupHeader)
        {
            ToolStripMenuItem headerToolStripMenuItem = new()
            {
                Name = menuCommand.Name,
                Text = menuCommand.Text,
                Enabled = false,
            };
            UserControls.RevisionGrid.MenuUtil.SetAsCaptionMenuItem(headerToolStripMenuItem);

            return headerToolStripMenuItem;
        }

        ToolStripMenuItem toolStripMenuItem = new()
        {
            Name = menuCommand.Name,
            Text = menuCommand.Text,
            Image = menuCommand.Image,
            ShortcutKeys = menuCommand.ShortcutKeys,
            ShortcutKeyDisplayString = menuCommand.ShortcutKeyDisplayString,
            ToolTipText = menuCommand.ToolTipText,
        };

        toolStripMenuItem.Click += (obj, sender) =>
        {
            if (menuCommand.ExecuteAction is not null)
            {
                menuCommand.ExecuteAction();
            }
            else
            {
                MessageBox.Show("No ExecuteAction assigned to this MenuCommand. Please submit a bug report.", TranslatedStrings.Error, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        };

        return toolStripMenuItem;
    }

    private readonly List<ToolStripMenuItem> _registeredMenuItems = [];

    /// <summary>
    /// if true all other properties have no meaning.
    /// </summary>
    public bool IsSeparator { get; set; }

    /// <summary>
    /// if true just text property have a meaning.
    /// </summary>
    public bool IsGroupHeader { get; set; }

    /// <summary>
    /// used for ToolStripItem and translation identification.
    /// </summary>
    public string? Name { get; set; }

    /// <summary>
    /// text of the menu item.
    /// </summary>
    public string? Text { get; set; }

    /// <summary>
    /// tooltip text of the menu item.
    /// </summary>
    public string? ToolTipText { get; set; }

    /// <summary>
    /// image of the menu item.
    /// </summary>
    public Image? Image { get; set; }

    public Keys ShortcutKeys { get; set; }

    public string? ShortcutKeyDisplayString { get; set; }

    /// <summary>
    /// execute on menu click.
    /// </summary>
    public Action? ExecuteAction;

    /// <summary>
    /// called if the menu item want to know if the Checked property
    /// should be true or false. If null then false.
    /// </summary>
    public Func<bool>? IsCheckedFunc;

    /// <summary>
    /// called if the menu item want to know if the Enabled property
    /// should be true or false. If null then true.
    /// </summary>
    public Func<bool>? IsEnabledFunc;

    /// <summary>
    /// To make the MenuCommand interact with all its associated menu items
    /// this method is used to register the all menu items that where generated by this MenuCommand.
    /// </summary>
    public void RegisterMenuItem(ToolStripMenuItem menuItem)
    {
        _registeredMenuItems.Add(menuItem);
    }

    public void UnregisterMenuItems(IEnumerable<ToolStripMenuItem> items)
    {
        foreach (ToolStripMenuItem item in items)
        {
            _registeredMenuItems.Remove(item);
        }
    }

    public void SetCheckForRegisteredMenuItems()
    {
        if (IsCheckedFunc is not null)
        {
            bool isChecked = IsCheckedFunc();

            foreach (ToolStripMenuItem item in _registeredMenuItems)
            {
                item.Checked = isChecked;
            }
        }

        if (IsEnabledFunc is not null)
        {
            bool isEnabled = IsEnabledFunc();

            foreach (ToolStripMenuItem item in _registeredMenuItems)
            {
                item.Enabled = isEnabled;
            }
        }
    }

    public void UpdateMenuItemsShortcutKeyDisplayString()
    {
        foreach (ToolStripMenuItem item in _registeredMenuItems)
        {
            item.ShortcutKeyDisplayString = ShortcutKeyDisplayString;
        }
    }
}
